package lifecycle

import (
	"fmt"
	"reflect"
	"sort"

	"go.uber.org/zap"
)

var lifes []Lifecycle = make([]Lifecycle, 0)

func Add(lifecycle Lifecycle) {
	lifes = append(lifes, lifecycle)
}

type Lifecycle interface {
	Start()
	Stop()
}

type LifecycleWithPriority interface {
	Priority() LifecyclePriority
}

type LifecycleRunner struct {
	lifecycle Lifecycle
	order     int //执行的顺序
}

// 生命周期启动
func Start() {
	lifecycleRunners := make([]LifecycleRunner, 0)
	for _, life := range lifes {
		var runner LifecycleRunner
		runner.lifecycle = life
		priority, ok := life.(LifecycleWithPriority)
		if ok {
			runner.order = int(priority.Priority().Layer)*10000 + int(priority.Priority().Sort)
		} else {
			runner.order = int(P_MEDIUM)*10000 + int(O_NORMAL)
		}
		lifecycleRunners = append(lifecycleRunners, runner)
	}
	//对执行顺序进行排序
	sort.Slice(lifecycleRunners, func(i int, j int) bool {
		return lifecycleRunners[i].order < lifecycleRunners[j].order
	})
	size := len(lifecycleRunners)
	for i := 0; i < size; i++ {
		runner := lifecycleRunners[i]
		lifeName := reflect.TypeOf(runner.lifecycle).Elem().Name()
		zap.L().Info(fmt.Sprintf("[%v/%v]%s starting...", i+1, size, lifeName))
		runner.lifecycle.Start()
		zap.L().Info(fmt.Sprintf("[%v/%v]%s started...", i+1, size, lifeName))
	}
}

// 生命周期停止
func Stop() {
	size := len(lifes)
	for i := size - 1; i >= 0; i-- {
		life := lifes[i]
		lifeName := reflect.TypeOf(life).Elem().Name()
		zap.L().Info(fmt.Sprintf("[%v/%v]%s stopping...", i+1, size, lifeName))
		life.Stop()
		zap.L().Info(fmt.Sprintf("[%v/%v]%s stopped...", i+1, size, lifeName))
	}
}

func KeepRunning() {
	emptyChan := make(chan string)
	for {
		data, ok := <-emptyChan
		fmt.Println("This will never happen, when happen, the server will stop!")
		if ok {
			zap.L().Info(data)
			break
		}
	}
}

type LifecyclePriority struct {
	Layer lifeLayer
	Sort  lifeSort
}

// 生命周期排序，正序启动，逆序关闭
// 第一优先级，生命周期所在的层面
type lifeLayer int

var P_INITIALIZATION lifeLayer = 0
var P_SYSTEM lifeLayer = 1
var P_HIGH lifeLayer = 2
var P_MEDIUM lifeLayer = 3
var P_LOW lifeLayer = 4

// 第二优先级，生命周期所在层面的顺序
type lifeSort int

var O_0 lifeSort = 0
var O_1 lifeSort = 1
var O_2 lifeSort = 2
var O_3 lifeSort = 3
var O_4 lifeSort = 4
var O_5 lifeSort = 5
var O_6 lifeSort = 6
var O_7 lifeSort = 7
var O_8 lifeSort = 8
var O_9 lifeSort = 9
var O_10 lifeSort = 10
var O_11 lifeSort = 11
var O_12 lifeSort = 12
var O_13 lifeSort = 13
var O_14 lifeSort = 14
var O_15 lifeSort = 15
var O_16 lifeSort = 16
var O_17 lifeSort = 17
var O_18 lifeSort = 18
var O_19 lifeSort = 19
var O_20 lifeSort = 20
var O_21 lifeSort = 21
var O_22 lifeSort = 22
var O_23 lifeSort = 23
var O_24 lifeSort = 24
var O_25 lifeSort = 25
var O_26 lifeSort = 26
var O_27 lifeSort = 27
var O_28 lifeSort = 28
var O_29 lifeSort = 29
var O_30 lifeSort = 30
var O_MIN lifeSort = O_0
var O_NORMAL lifeSort = O_15
var O_MAX lifeSort = O_30
